local skel = fk.CreateSkill {
  name = "lb__yongyi",
  tags = { Skill.Compulsory, }
}

Fk:loadTranslationTable {
  ["lb__yongyi"] = "永屹",
  [":lb__yongyi"] = "<b>锁定技</b>，你的牌本回合首次被其他角色弃置后，你获得之。" ..
      "当你死亡后，成为过你<a href=':lb__zhenshu'><font color='red'>〖镇戍〗</font></a>目标的角色攻击范围+1，且本局游戏你仍参与距离计算。",

  ["@@lb__yongyi"] = "永屹",

  ["$lb__yongyi1"] = "有我在。",
  ["$lb__yongyi2"] = "正义已至！",
}

skel:addEffect(fk.AfterCardsMove, {
  anim_type = "defensive",
  can_trigger = function(self, event, target, player, data)
    if not player:hasSkill("lb__yongyi") then return false end
    local ids = {}
    local room = player.room
    local event_id = room.logic:getCurrentEvent().id

    for _, move in ipairs(data) do
      if move.from and move.from == player and move.toArea == Card.DiscardPile
          and move.moveReason == fk.ReasonDiscard and move.proposer and move.from ~= move.proposer then
        if #room.logic:getEventsOfScope(GameEvent.MoveCards, 1, function(e)
              for _, m in ipairs(e.data) do --完全一致的筛选
                if m.toArea == Card.DiscardPile then
                  if m.moveReason == fk.ReasonDiscard and m.from and m.proposer and m.from ~= m.proposer
                      and m.from == move.from then
                    for _, info in ipairs(m.moveInfo) do
                      if (info.fromArea == Card.PlayerHand or info.fromArea == Card.PlayerEquip) and
                          e.id ~= event_id then
                        return true
                      end
                    end
                  end
                end
              end
            end, Player.HistoryTurn) > 0 then
          return
        end

        for _, info in ipairs(move.moveInfo) do
          if (info.fromArea == Card.PlayerHand or info.fromArea == Card.PlayerEquip) and
              room:getCardArea(info.cardId) == Card.DiscardPile then
            table.insertIfNeed(ids, info.cardId)
          end
        end
      end
    end
    ids = player.room.logic:moveCardsHoldingAreaCheck(ids)
    if #ids > 0 then
      event:setCostData(self, { ids = ids })
      return true
    end
  end,
  on_use = function(self, event, target, player, data)
    player.room:obtainCard(player, event:getCostData(self).ids, true, fk.ReasonJustMove, player, "lb__yongyi")
  end,
})

skel:addEffect(fk.Death, {
  can_refresh = function(self, event, target, player, data)
    return target == player and player:hasSkill(skel.name, false, true) and #player:getTableMark("lb__yongyi") > 0
  end,
  on_refresh = function(self, event, target, player, data)
    local room = player.room
    for _, p in ipairs(player:getTableMark("lb__yongyi")) do
      room:setPlayerMark(room:getPlayerById(p), "@@lb__yongyi", 1)
    end
  end,
})

---@param player Player @ 其他玩家
---@param other Player @ 其他玩家
---@param mode? string @ 计算模式(left/right/both)
---@param ignore_dead? boolean @ 是否忽略尸体
---@param excludeIds? integer[] @ 忽略的自己装备的id列表，用于飞刀判定
---@param excludeSkills? string[] @ 忽略的技能名列表
local function distanceTo(player, other, mode, ignore_dead, excludeIds, excludeSkills)
  assert(other:isInstanceOf(Player))
  mode = mode or "both"
  excludeSkills = excludeSkills or {}
  if excludeIds then
    for _, id in ipairs(excludeIds) do
      local equip = player:getVirualEquip(id) --[[@as EquipCard]]
      if equip == nil and table.contains(player:getCardIds("e"), id) and Fk:getCardById(id).type == Card.TypeEquip then
        equip = Fk:getCardById(id) --[[@as EquipCard]]
      end
      if equip and equip.type == Card.TypeEquip then
        for _, skill in ipairs(equip:getEquipSkills(player)) do
          table.insertIfNeed(excludeSkills, skill.name)
        end
      end
    end
  end
  if other == player then return 0 end
  if not ignore_dead and other.dead then
    return -1
  end
  if player:isRemoved() or other:isRemoved() then
    return -1
  end
  local right = 0
  local temp = player
  local try_time = 10
  for _ = 0, try_time do
    if temp == other then break end
    if (
          --((ignore_dead or not temp.dead) and not temp:isRemoved()) or
           (temp:hasSkill("lb__yongyi", false, true) and temp.dead) or 
           (not temp.dead and not temp:isRemoved())
        ) then
      right = right + 1
    end
    temp = temp.next
  end
  if temp ~= other then
    print("Distance malfunction: start and end does not match.")
  end
  --local left = #(ignore_dead and Fk:currentRoom().players or Fk:currentRoom().alive_players) - right -
  --#table.filter(Fk:currentRoom().alive_players, function(p) return p:isRemoved() end)
  local left = 0
  temp = player
  for _ = 0, try_time do
    if temp == other then break end
    if (
          --((ignore_dead or not temp.dead) and not temp:isRemoved()) or
           (temp:hasSkill("lb__yongyi", false, true) and temp.dead) or 
           (not temp.dead and not temp:isRemoved())
        ) then
      left = left + 1
    end
    temp = table.find(Fk:currentRoom().players, function (to)
      local seat = (temp.seat == 1 and #Fk:currentRoom().players or temp.seat - 1)
      return to.seat == seat
    end)
    if temp == nil then break end
    --temp = temp.next
  end
  if temp ~= other then
    print("Distance malfunction: start and end does not match.")
  end
  local ret = 0
  if mode == "left" then
    ret = left
  elseif mode == "right" then
    ret = right
  else
    ret = math.min(left, right)
  end

  local status_skills = Fk:currentRoom().status_skills[DistanceSkill] or Util.DummyTable ---@type DistanceSkill[]
  for _, skill in ipairs(status_skills) do
    if not table.contains(excludeSkills, skill.name) then
      local fixed = skill:getFixed(player, other)
      local correct = skill:getCorrect(player, other)
      if fixed ~= nil then
        ret = fixed
        break
      end
      ret = ret + (correct or 0)
    end
  end

  return math.max(ret, 1)
end


skel:addEffect("distance", {
  fixed_func = function(self, from, to)
    --[[
    local room = Fk:currentRoom()
    local tos = table.filter(room.players, function (temp)
      return temp:hasSkill("lb__yongyi", false, true) and temp.dead
    end)
    if #tos > 0 then
      --local num = from:distanceTo(to, "both", true, nil, { self.name })
      return distanceTo(from, to, "both", true, nil, { self.name })
    end
    --]]
    return distanceTo(from, to, "both", true, nil, { self.name })
  end,
})

skel:addEffect("atkrange", {
  correct_func = function(self, from, to)
    if from:getMark("@@lb__yongyi") > 0 then
      return 1
    end
  end,
})

return skel